﻿#region using statements

using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using NGen;
using NGen.Managers.GameObject;
using NGen.Systems.StringAlarms;

using TowerDefense.Misc;

#endregion

namespace TowerDefense.Objects.Enemies
{
	/// <summary>
	/// 	Control game object which simply spawns enemies at a set interval
	/// </summary>
	public class GameObjectEnemySpawner : GameObject, IAlarmListener
	{
		#region local fields

		/// <summary>
		/// 	alarm system to delay the enemy spawns
		/// </summary>
		private readonly AlarmSystem m_alarm = new AlarmSystem();

		/// <summary>
		/// 	the list of enemies which this spawner will create
		/// </summary>
		private readonly Queue<GameObjectEnemyBase> m_qEnemies = new Queue<GameObjectEnemyBase>();

		/// <summary>
		/// 	color to use for enemies created by this spawner
		/// </summary>
		private Color m_randomColor;

		/// <summary>
		/// 	texture to use for enemies created by this spawner
		/// </summary>
		private Texture2D m_randomTexture;

		#endregion

		#region local methods

		/// <summary>
		/// 	Add an enemy to this spawner
		/// </summary>
		/// <param name = "enemy">the enemy to add</param>
		public void AddEnemy(GameObjectEnemyBase enemy) {
			var level = GameEngine.GetService<GameLevel>();
			enemy.m_position = GameLevel.GetScreenCoords(level.StartPosition);
			m_qEnemies.Enqueue(enemy);
			enemy.m_texture = m_randomTexture;
			enemy.m_textureTint = m_randomColor;
		}

		#endregion

		#region GameObject implementation

		/// <summary>
		/// 	_Initialize the spawner, creates the first alarm which will begin
		/// 	spawning the loaded enemies
		/// </summary>
		protected override void _Initialize() {
			m_alarm.Add(new AlarmObject(this, 1.0, "spawnNext"));

			switch(GameEngine.Random.Next(3)) {
					//set the texture to user
				case 0:
					m_randomTexture = GameEngine.GameContent.Load<Texture2D>("Content\\Textures\\Enemies\\Cone");
					break;
				case 1:
					m_randomTexture = GameEngine.GameContent.Load<Texture2D>("Content\\Textures\\Enemies\\Hex");
					break;
				case 2:
					m_randomTexture = GameEngine.GameContent.Load<Texture2D>("Content\\Textures\\Enemies\\Square");
					break;
			}

			//set the color to use
			m_randomColor = new Color(GameEngine.Random.Next(255), //R
			                          GameEngine.Random.Next(255), //G
			                          GameEngine.Random.Next(255)); //B
		}

		/// <summary>
		/// 	Update the spawner for this frame
		/// </summary>
		/// <param name = "p_gameTime">snapshot of timing values</param>
		protected override void _Update(GameTime p_gameTime) {
			m_alarm.Update(p_gameTime);
		}

		/// <summary>
		/// 	Draw the spawner for this frame
		/// </summary>
		/// <param name = "p_gameTime">snapshot of timing values</param>
		protected override void _Draw(GameTime p_gameTime) {}

		/// <summary>
		/// 	Cleanup the spawner
		/// </summary>
		protected override void _Cleanup() {}

		#endregion

		#region IAlarmListener implementation

		/// <summary>
		/// 	Callback used whenever an alarm goes off
		/// </summary>
		/// <param name = "message">the message from the alarm</param>
		public void OnAlarmEvent(string message) {
			switch(message) {
				case "spawnNext": //spawn a new enemy

					//add it to the enemy list
					GameEngine.GetService<EnemyList>().Add(m_qEnemies.Peek());

					//add it to the object manager so that it gets updated/drawn
					GameEngine.GetService<IManagerGameObjects>().AddObject(m_qEnemies.Dequeue());

					//if there are more enemies to spawn, reset the alarm
					if(m_qEnemies.Count > 0) {
						m_alarm.Add(new AlarmObject(this, 0.3, "spawnNext"));
					} else {
						//else destroy this spawner
						Destroy(Id);
					}
					break;
			}
		}

		#endregion
	}
}